#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Handles requests made to movietimes/get/*""" 

# Import packages
import datetime
import wsgiref.handlers

from google.appengine.api import memcache
from google.appengine.api import urlfetch
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

from vinnyslibs import tz, xml2json2
from xml.dom import minidom


FEED_URL = "http://www.XXXXXX.com.XX/_feed/XXXXXX/cinema_%s_%s.xml"


class Feed(db.Model):
    """Feed Model representing a movie feed for a particular country and date"""
    countryCode = db.StringProperty(required=True) #composite key
    dateString = db.StringProperty(required=True)  #composite key
    jsonText = db.TextProperty()
    

class GetFeedHandler(webapp.RequestHandler):
    """Handles requests for /get/country/outputformat"""
    
    def __init__(self):
        self.validCountries = ['my','sg']
        self.validFormats = ['json','xml']
        self.strToday = self.getTodayDateStr()
        self.country = None
        self.memcachekey = None
    
    def get(self, country, format):
        if country not in self.validCountries:
            print 'not valid country %s' % country
            self.error(400)
        elif format not in self.validFormats:
            print 'not valid format %s' % format
            self.error(400)
        
        self.country = country
        self.memcachekey = "%s_%s" % (self.country, self.strToday)
        
        #Check if json is in memory or DB already
        jsonm = memcache.get(self.memcachekey)
        if jsonm is None:
            jsonq = db.GqlQuery("SELECT * \
                                FROM Feed \
                                WHERE countryCode = :1 \
                                  AND dateString = :2", 
                                self.country, self.strToday)
            jsons = jsonq.fetch(1,0)
            if len(jsons) >= 1:
                json = jsons[0].jsonText
                memcache.set(self.memcachekey, json)
                return self.outputJSON(json)
            else:
                return self.fetchFeed()
        else:
            return self.outputJSON(jsonm)    
         
        
    def getTodayDateStr(self):
        """Return today's date in the format YYYYMMDD"""
        utc = tz.UtcTzinfo()
        sst = tz.SstTzinfo()
        datetime_utc = datetime.datetime.utcnow()
        #even though datetime_now is in UTC, still need to call the replace() method
        # in order for astimezone() method to work
        datetime_utc = datetime_utc.replace(tzinfo=utc)
        datetime_sst = datetime_utc.astimezone(sst)
            
        str = datetime_sst.strftime('%Y%m%d')
        return str
    
    
    def fetchFeed(self):
        """Fetch and process the XML feed for the first time"""
        feedURL = FEED_URL % (self.country, self.strToday)
        fetchResult = urlfetch.fetch(feedURL)
        if fetchResult.status_code == 200:
            self.parseFeed(fetchResult.content)
        else:
            #Feed fetch was unsuccessful, return an error code
            self.error(500)
            
            
    def parseFeed(self, feed):
        """Parse XML feed, convert to JSON, store JSON in cache, output JSON"""
        xmldom = minidom.parseString(feed)
        parser = xml2json2.ParseMovieFeed(xmldom, self.strToday)
        parser.parse()
        
        json = parser.getJSON()
        self.storeJSON(json)
        self.outputJSON(json)
        
        
    def storeJSON(self, json):
        """Store the new JSON string in memcache and as a Feed model"""
        memcache.set(self.memcachekey, json)
        
        feed = Feed(countryCode=self.country, dateString=self.strToday)
        feed.jsonText = json
        feed.put()    
        
        
    def outputJSON(self, json):
        """Output the JSON content with appropriate HTTP headers"""
        self.response.headers['Content-Type'] = 'application/json'
        self.response.out.write(json)
        
class DefaultHandler(webapp.RequestHandler):
    def get(self):
        self.response.out.write('')


def main():
  application = webapp.WSGIApplication([('/movietimes/get/(.*?)/(\w*).*', GetFeedHandler)],
                                       debug=True)
  run_wsgi_app(application)


if __name__ == '__main__':
  main()